/* 学习 TS
  + 是个什么 ?
    => 全名叫做 TypeScript
    => 作用: 给 js 内的 **每一个** 数据添加一个类型限制
    => 因为 JS 的弱类型会导致有的时候出现问题是因为类型错误
    => 例子 :
      function fn(a, b) { return a + b }
      => fn(10, 20)       可以得到一个正常的结果 30
      => fn('10', '20')   得到一个结果 '1020'
      => 从 js 的角度来看, 上面的代码都是没有问题的
      => 这个时候就是因为类型错误, 导致的最终结果错误
    => 大家就想在开发过程中, 能把类型限制的稍微严谨一些, 并且一旦出现类型错误, 马上提示我
    => 所以就出现了 TypeScript
      -> 最终 TS 还是要被编译成 JS 在浏览器端运行
*/

/* 1. TS 对基本数据类型的限制
  + 在变量名后面写上数据类型即可
  + 示例: let n: number = 0
  + 此时, 该 n 变量被限制为 number 类型, 今后只能存储 number 类型的数据, 其他数据类型不行
  + 基本类型限制内有一个内容叫做 void
    => 一般用来表示函数的返回值
*/
// let n: number = 0
// n = 100
// n = 200
// n = true
// let s: string = 'hello'
// s = 'world'
// s = "你好"
// s = `世界`
// s = 200
// let boo: boolean = true
// boo = false
// boo = 10
// 数据类型的限制, 可以用在任何一个书写数据的位置
// function fn(a: number, b: number) {
//   return a + b
// }
// // 今后使用这个函数的时候
// fn(10, 20)
// fn(100, 200)
// 表示该函数没有返回值, 也不能有返回值
// function fn(): void {
//   return 123
// }

/* 2. TS 的接口( interface )
  + 是对引用数据类型( 主要是 : 对象 和 数组 )
  + 创建接口
    interface 接口名称 {
      key: 数据类型,
      ...
    }
  + 如果在接口内你想定义选填的 key
    => 在 key 的后面加上一个 问号( ? )
  + 如果在接口内你想定义只读的 key( 不允许修改 )
    => 在 key 的前面加上一个 readonly 关键字
*/
// 创建一个接口
// 创建了一个叫做 UserType 的接口, 将来可以用来去限制一个数据
// 被他限制的数据要求
//   数据结构内必须要有一个叫做 name 的 key, 并且值是 string 类型
//   数据结构内必须要有一个叫做 age 的 key, 并且值是 number 类型
//   数据结构内可以有一个叫做 gender 的 key, 并且值是 string 类型
//   数据结构内必须有一个叫做 score 的 key, 并且值是 number 类型, 并且该值一旦赋值, 不允许被修改
// interface UserType {
//   name: string
//   age: number
//   gender?: string
//   readonly score: number
// }
//
// const user: UserType = {
//   name: 'Jack',
//   age: 18,
//   gender: '男',
//   score: 100
// }
// 接口是可以被继承的
// interface PersonType {
//   name: string
//   age: number
//   gender: string
// }
//
// interface StudentInfoType extends PersonType {
//   score: number
//   stu_id: number
// }
//
// interface TeacherInfoType extends PersonType {
//   work_id: number
// }
// 创建纯路人
// const user1: PersonType = { name: 'Jack', age: 18, gender: '男' }
// const user2: StudentInfoType = { name: 'Jack', age: 18, gender: '男', score: 100, stu_id: 23 }
// const user3: TeacherInfoType = { name: 'Jack', age: 18, gender: '男', work_id: 2208 }
// 商品列表页的商品 { 名称, 图片, 价格, 描述 }
// 商品详情页的商品 { 名称, 图片, 价格, 描述, 详细介绍, 参数介绍, 规格介绍, ... }
// 购物车页面的商品 { 名称, 图片, 价格, 描述, 购买数量, 库存, 折扣类型, ... }

/* 3. 数组的限制
  + 对数组数据类型的限制
  + 有两种语法
    => 语法1: const list: number[] = []
    => 语法2: const list: Array<string> = []
*/
// 语法1:
// const list: number[] = [ 100, 200, 300 ]
// const list2: Array<number> = [ 10, 20, 30, 40 ]
// interface PersonType {
//   name: string
//   age: number
//   gender: string
//   hobby?: string[]
// }
// 这个 userList 数组将来只能存储由 PersonType 类型限制过得数据
// const userList: PersonType[] = [
//   { name: 'Jack', age: 18, gender: '男' },
//   { name: 'Rose', age: 20, gender: '女', hobby: [ '钢琴', '小提琴' ] },
//   { name: 'Jerry', age: 22, gender: '男' }
// ]

/* 4. 约束( 别名 )
  + 语法: type 约束名称 = 值1 | 值2 | 值3 | ...
*/
// 一般用来将几个类型或者常量进行组合
// let a: number | string = 100
// a = 'hello'
// let b: number | string = 'world'
// b = 200
// 创建一个约束
// type AbcType = number | string
// let a: AbcType = 100
// a = 'hello'
// let b: AbcType = 'world'
// b = 200
// 例子: 假设你要做一个 红绿灯 的案例, 那么你的可选颜色 红 黄 绿
// 可以利用 type 来制作一个 常量约束
// type ColorType = 'red' | 'green' | 'yellow'
// // 利用制作好的 type 约束, 去限制变量的数据类型
// let color: ColorType = 'red'
// color = 'green'
// color = 'yellow'
// color = 'orange'
// interface PersonType {
//   name: string
//   age: number
//   gender: string
// }
// type StudentInfoType = PersonType & {
//   score: number
//   stu_id: number
// }
// type StudentInfoType2 = PersonType | {
//   score: number
//   stu_id: number
// }
// const user: StudentInfoType = { score: 100, stu_id: 23, name: 'Jack', age: 20, gender: '男' }
// const user2: StudentInfoType2 = { score: 200, stu_id: 30 }
